package com.corpgovernment.costcenter.service.impl;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.corpgovernment.api.applytrip.applyquery.response.ApplyTripCostCenterResponse;
import com.corpgovernment.api.applytrip.soa.response.ApplyTripDetailResponse;
import com.corpgovernment.api.costcenter.model.*;
import com.corpgovernment.api.costcenter.service.ICostCenterService;
import com.corpgovernment.api.operatelog.vo.OperateLogContentDataVo;
import com.corpgovernment.api.organization.model.enums.WholeGroupQueryEnum;
import com.corpgovernment.api.organization.model.org.GetOrgTreeResponse;
import com.corpgovernment.api.organization.model.org.OrgInfoVo;
import com.corpgovernment.api.organization.model.org.request.AddOrgRequest;
import com.corpgovernment.api.organization.soa.IOrganizationClient;
import com.corpgovernment.api.organization.utils.UuidUtil;
import com.corpgovernment.api.organization.vo.GetOrgTreeRsp;
import com.corpgovernment.common.apollo.OrganizationApollo;
import com.corpgovernment.common.base.BaseUserInfo;
import com.corpgovernment.common.base.JSONResult;
import com.corpgovernment.common.base.Page;
import com.corpgovernment.common.base.ResourceInfo;
import com.corpgovernment.common.common.CorpBusinessException;
import com.corpgovernment.common.enums.ExceptionCodeEnum;
import com.corpgovernment.common.operatelog.constant.OperateLogContant;
import com.corpgovernment.common.utils.DataPermissions.DataPermissionsContext;
import com.corpgovernment.common.utils.DateUtil;
import com.corpgovernment.common.utils.Null;
import com.corpgovernment.common.utils.ObjectStringTrimUtils;
import com.corpgovernment.costcenter.entity.db.*;
import com.corpgovernment.costcenter.mapper.*;
import com.corpgovernment.costcenter.model.CostCenterExcelInsertBo;
import com.corpgovernment.costcenter.model.CostCenterUploadExcelInfo;
import com.corpgovernment.costcenter.vo.*;
import com.corpgovernment.organization.Bo.SyncEmployeeInfoBo;
import com.corpgovernment.organization.constant.OrganizationResponseCodeEnum;
import com.corpgovernment.organization.dataloader.ApplyTripClientLoader;
import com.corpgovernment.organization.entity.SyncEmployeeCallBackRequestEntity;
import com.corpgovernment.organization.entity.db.MbOrgInfo;
import com.corpgovernment.organization.enumm.ExcelPostEnum;
import com.corpgovernment.organization.operatelog.service.pojo.CostCenterPojo;
import com.corpgovernment.organization.service.IOrganizationInfoService;
import com.corpgovernment.organization.util.ExcelUtils;
import com.corpgovernment.organization.util.StrUtils;
import com.corpgovernment.organization.vo.ExcelCreateVO;
import com.corpgovernment.organization.vo.GetOrgTreeRequest;
import com.ctrip.corp.obt.generic.core.context.RequestContext;
import com.ctrip.corp.obt.generic.core.context.UserInfoContext;
import com.ctrip.corp.obt.generic.utils.CollectionUtils;
import com.ctrip.corp.obt.generic.utils.JsonUtils;
import com.ctrip.corp.obt.generic.utils.StringUtils;
import com.ctrip.corp.obt.shard.context.PageContext;
import com.ctrip.corp.obt.shard.sql.mybatis.interceptor.pagination.IPage;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import tk.mybatis.mapper.entity.Example;

import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.function.Function;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import static com.corpgovernment.permission.config.PermissionFilter.DATA_PERMISSION_ORG_ID_LIST;

@Service
@Slf4j
public class CostCenterServiceImpl implements ICostCenterService {

    @Autowired
    private IOrganizationClient organizationService;
    @Autowired
    private MbOrgCostInfoMapper orgCostInfoMapper;
    @Autowired
    private MbOrgCostDepartmentMapper orgCostDepartmentMapper;
    @Autowired
    private ApplyTripClientLoader applyTripClientLoader;
    @Autowired
    private ExcelUtils excelUtils;
    @Autowired
    private IOrganizationInfoService organizationInfoService;
    @Autowired
    private MbOrgCostUploadMapper mbOrgCostUploadMapper;
    @Autowired
    private MbOrgCostUploadDetailMapper mbOrgCostUploadDetailMapper;
    @Autowired
    private MbOrgCostDefaultDepartmentMapper mbOrgCostDefaultDepartmentMapper;
    @Autowired
    private OrganizationApollo organizationApollo;
    @Autowired
    @Qualifier(value = "getValidPassengerThreadPoolExecutor")
    private ThreadPoolExecutor getValidPassengerThreadPoolExecutor;

    @Override
    public int insert(CostCenter model) {

        StrUtils.fieldRemoveSpace(model);

        List<MbOrgCostInfo> costInfos = this.select(model);
        boolean duplicateCode =
                costInfos.stream().anyMatch(e -> Objects.equals(e.getCostCenterCode(), model.getCostCenterCode()));
        if (duplicateCode) { // 判断编码是否重复
            return 0;
        }

        MbOrgCostInfo costInfo = transfer(model);
        costInfo.setUpdateTime(new Date());
        costInfo.setCreateTime(new Date());

        orgCostInfoMapper.insert(costInfo);
        int saveId = costInfo.getId();
        model.setId(costInfo.getId());
        if (model.getDepartments() != null && model.getDepartments().size() > 0) { // 插入部门数据
            List<MbOrgCostDepartment> departments = new ArrayList<>();
            for (OrgInfo orgInfo : model.getDepartments()) {
                MbOrgCostDepartment costDepartment = new MbOrgCostDepartment();
                costDepartment.setCostInfoId(costInfo.getId());
                costDepartment.setOrgId(orgInfo.getOrgId());
                costDepartment.setOrgName(orgInfo.getName());
                costDepartment.setCreateTime(new Date());
                costDepartment.setUpdateTime(new Date());
                departments.add(costDepartment);
            }
            orgCostDepartmentMapper.insertList(departments);
        }

        for (OrgInfo orgInfo : model.getDepartments()) {
            if (BooleanUtils.isTrue(orgInfo.getIsDefault())) {
                MbOrgCostDefaultDepartment mbOrgCostDefaultDepartment =
                        this.selectDefaultDepartmentByOrgId(orgInfo.getOrgId());
                if (Objects.isNull(mbOrgCostDefaultDepartment)) {
                    // 该组织未设置默认成本中心 直接绑定该成本中心未默认成本中心
                    MbOrgCostDefaultDepartment defaultDepartment = new MbOrgCostDefaultDepartment();
                    defaultDepartment.setCostInfoId(costInfo.getId());
                    defaultDepartment.setOrgId(orgInfo.getOrgId());
                    defaultDepartment.setCreateTime(new Date());
                    defaultDepartment.setUpdateTime(new Date());
                    defaultDepartment.setIsDelete(false);
                    mbOrgCostDefaultDepartmentMapper.insert(defaultDepartment);
                } else {
                    mbOrgCostDefaultDepartment.setCostInfoId(costInfo.getId());
                    mbOrgCostDefaultDepartment.setUpdateTime(new Date());
                    mbOrgCostDefaultDepartmentMapper.updateByPrimaryKeySelective(mbOrgCostDefaultDepartment);
                }
            }
        }
        return saveId;
    }

    @Override
    public int delete(Map map) {
        Integer id = Integer.parseInt(map.get("id").toString());
        MbOrgCostInfo costInfo = orgCostInfoMapper.selectByPrimaryKey(id);
        if (costInfo == null) {
            return 2;
        }

        this.deleteCostInfoByPKId(id);
        this.deleteDefaultDepartmentByCostId(id);
        return 1;
    }

    public boolean deleteCostInfoByPKId(int id) {
        MbOrgCostInfo mbOrgCostInfo = new MbOrgCostInfo();
        mbOrgCostInfo.setIsDelete(true);
        mbOrgCostInfo.setUpdateTime(new Date());
        mbOrgCostInfo.setId(id);
        return orgCostInfoMapper.updateByPrimaryKeySelective(mbOrgCostInfo) > 0;
    }

    public List<MbOrgCostInfo> select(CostCenter model) {
        if (model == null) {
            return new ArrayList<>();
        }
        return orgCostInfoMapper.selectByCompanyId(model.getCompanyId());
    }

    @Override
    public int update(CostCenter model) {

        StrUtils.fieldRemoveSpace(model);

        MbOrgCostInfo costInfo = orgCostInfoMapper.selectByPrimaryKey(model.getId());
        if (costInfo != null) {
            if (!StringUtils.isBlank(model.getCostCenterCode())) {
                List<MbOrgCostInfo> costInfos = this.select(model);
                costInfos =
                        costInfos.stream().filter(e -> Objects.equals(e.getCostCenterCode(), model.getCostCenterCode()))
                                .collect(Collectors.toList());
                for (MbOrgCostInfo item : costInfos) {
                    if (!item.getId().equals(model.getId())) {
                        return 0;// 名称重复且id不同
                    }
                }
            }

            Example updateExample = new Example(MbOrgCostInfo.class);
            updateExample.createCriteria().andEqualTo("id", model.getId());
            MbOrgCostInfo updateCostInfo = transfer(model);
            updateCostInfo.setUpdateTime(new Date());
            orgCostInfoMapper.updateByExampleSelective(updateCostInfo, updateExample);
            if(Objects.isNull(updateCostInfo.getValidStartDate())||Objects.isNull(updateCostInfo.getValidEndDate())){
                if (Objects.isNull(updateCostInfo.getId())){
                    log.error("成本中心有效时间更新失败，成本中心ID为空：{}",updateCostInfo.getId());
                }else {
                    orgCostInfoMapper.updateCostValidDate(updateCostInfo);
                }

            }

            // 先删除原有数据
            Example example = new Example(MbOrgCostDepartment.class);
            example.createCriteria().andEqualTo("costInfoId", model.getId());
            orgCostDepartmentMapper.deleteByExample(example);
            // 插入新的关系数据
            List<MbOrgCostDepartment> departments = new ArrayList<>();
            for (OrgInfo orgInfo : model.getDepartments()) {
                MbOrgCostDepartment costDepartment = new MbOrgCostDepartment();
                costDepartment.setCostInfoId(costInfo.getId());
                costDepartment.setOrgId(orgInfo.getOrgId());
                costDepartment.setOrgName(orgInfo.getName());
                costDepartment.setCreateTime(new Date());
                costDepartment.setUpdateTime(new Date());
                departments.add(costDepartment);
            }
            orgCostDepartmentMapper.insertList(departments);

            this.deleteDefaultDepartmentByCostId(model.getId());
            for (OrgInfo orgInfo : model.getDepartments()) {
                if (BooleanUtils.isTrue(orgInfo.getIsDefault())) {
                    MbOrgCostDefaultDepartment mbOrgCostDefaultDepartment =
                            this.selectDefaultDepartmentByOrgId(orgInfo.getOrgId());
                    if (Objects.isNull(mbOrgCostDefaultDepartment)) {
                        // 该组织未设置默认成本中心 直接绑定该成本中心未默认成本中心
                        MbOrgCostDefaultDepartment defaultDepartment = new MbOrgCostDefaultDepartment();
                        defaultDepartment.setCostInfoId(costInfo.getId());
                        defaultDepartment.setOrgId(orgInfo.getOrgId());
                        defaultDepartment.setCreateTime(new Date());
                        defaultDepartment.setUpdateTime(new Date());
                        defaultDepartment.setIsDelete(false);
                        mbOrgCostDefaultDepartmentMapper.insert(defaultDepartment);
                    } else {
                        mbOrgCostDefaultDepartment.setCostInfoId(costInfo.getId());
                        mbOrgCostDefaultDepartment.setUpdateTime(new Date());
                        mbOrgCostDefaultDepartmentMapper.updateByPrimaryKeySelective(mbOrgCostDefaultDepartment);
                    }
                }
            }
            return 1;
        } else {// 该条记录不存在
            return 2;
        }
    }

    @Override
    public GetCostCenterListResponse queryCostCenterInfos(GetCostCenterListRequest request) {
        log.info("成本中心查询参数: " + request);

        List<CostCenter> costCenterList = new ArrayList<CostCenter>();
        GetCostCenterListResponse response = new GetCostCenterListResponse();
        // 获取业务系统
        List<BusinessSystem> businessList = null;
        response.setBusinessList(businessList);// 业务系统在Apollo里配置
        Example example = new Example(MbOrgCostInfo.class);
        Example.Criteria exampleJoin = example.createCriteria()
                .andEqualTo("isDelete", false);
        // 查询全集团数据
        boolean findWholeGroup = WholeGroupQueryEnum.APPROVE.getCode().equals(request.getWholeGroupQuery())
                && organizationApollo.enableApproveShowAllOrg();
        if(!findWholeGroup){ // 不是查全集团数据,就需要添加查询条件companyId进行过滤
            exampleJoin.andEqualTo("companyId", request.getOrgId());
        }

        if (!StringUtils.isBlank(request.getKey())) {
            List<MbOrgCostInfo> orgCostInfoList = orgCostInfoMapper.listAll();
            List<Integer> ids = orgCostInfoList.stream()
                    .filter(e -> StringUtils.contains(e.getCostCenterName(), request.getKey())
                            || StringUtils.contains(e.getCostCenterCode(), request.getKey()))
                    .map(MbOrgCostInfo::getId)
                    .collect(Collectors.toList());
            if (CollectionUtils.isEmpty(ids)) {
                return response;
            }
            exampleJoin.andIn("id", ids);
        }
        example.setOrderByClause("datachange_lasttime DESC");
        PageHelper.startPage(request.getCurrentPage(), request.getPageSize());
        List<MbOrgCostInfo> costInfos = orgCostInfoMapper.selectByExample(example);
        PageInfo pageInfo = new PageInfo<>(costInfos);
        Page<MbOrgCostInfo> page = new Page(pageInfo.getPageNum(), pageInfo.getPageSize(), pageInfo.getPages(),
                pageInfo.getTotal(), costInfos);

        for (MbOrgCostInfo info : page.getList()) {
            CostCenter item = transfer(info);

            Example DpExample = new Example(MbOrgCostDepartment.class);
            DpExample.createCriteria().andEqualTo("costInfoId", info.getId());
            List<MbOrgCostDepartment> departments = orgCostDepartmentMapper.selectByExample(DpExample);

            List<MbOrgCostDefaultDepartment> departmentList = this.selectDefaultDepartmentByCostId(info.getId());
            Map<String, MbOrgCostDefaultDepartment> defaultDepartmentMap = departmentList.stream().collect(
                    Collectors.toMap(MbOrgCostDefaultDepartment::getOrgId, Function.identity(), (k1, k2) -> k1));
            List<OrgInfo> orgInfos = new ArrayList<>();
            for (MbOrgCostDepartment dp : departments) {
                OrgInfo orgInfo = new OrgInfo();
                orgInfo.setName(dp.getOrgName());
                orgInfo.setOrgId(dp.getOrgId());
                if (Objects.nonNull(defaultDepartmentMap.get(dp.getOrgId()))) {
                    orgInfo.setIsDefault(Boolean.TRUE);
                } else {
                    orgInfo.setIsDefault(Boolean.FALSE);
                }
                orgInfos.add(orgInfo);
            }
            item.setDepartments(orgInfos);
            costCenterList.add(item);
        }
        response.setCostCenterList(costCenterList);// 返回前端结果
        response.setCurrentPage(request.getCurrentPage());
        response.setPageSize(request.getPageSize());
        response.setTotalCount(Integer.valueOf(page.getCount().toString()));
        response.setTotalPage(page.getTotalPage());
        log.info("成本中心查询结果: " + response);
        return response;
    }

    public CostCenterPojo convert(GetCostCenterListRequest request) {
        // 获取业务系统
        PageHelper.startPage(1, 2);
        Example example = new Example(MbOrgCostInfo.class);
        example.createCriteria().andEqualTo("companyId", request.getOrgId()).andEqualTo("isDelete", false);
        example.setOrderByClause("datachange_lasttime DESC");
        List<MbOrgCostInfo> costInfos = orgCostInfoMapper.selectByExample(example);
        PageInfo pageInfo = new PageInfo<>(costInfos);
        Page<MbOrgCostInfo> page = new Page(pageInfo.getPageNum(), pageInfo.getPageSize(), pageInfo.getPages(),
                pageInfo.getTotal(), costInfos);
        CostCenterPojo costCenterPojo = new CostCenterPojo();
        if (page != null && !CollectionUtils.isEmpty(page.getList())) {
            MbOrgCostInfo mbOrgCostInfo = page.getList().get(0);
            costCenterPojo.setCostCenterCode(mbOrgCostInfo.getCostCenterCode());
            costCenterPojo.setCostCenterName(mbOrgCostInfo.getCostCenterName());
            if (mbOrgCostInfo.getValid() == null) {
                costCenterPojo.setValid(OperateLogContant.INVALID);
            } else {
                if (mbOrgCostInfo.getValid()) {
                    costCenterPojo.setValid(OperateLogContant.VALID);
                } else {
                    costCenterPojo.setValid(OperateLogContant.INVALID);
                }
            }
            costCenterPojo.setCreateDate(DateUtil.dateToString(mbOrgCostInfo.getUpdateTime(), DateUtil.DF_YMD_HMS));
            costCenterPojo.setValidStartDate(mbOrgCostInfo.getValidStartDate());
            costCenterPojo.setValidEndDate(mbOrgCostInfo.getValidEndDate());
            Example DpExample = new Example(MbOrgCostDepartment.class);
            DpExample.createCriteria().andEqualTo("costInfoId", mbOrgCostInfo.getId());

            List<MbOrgCostDepartment> departments = orgCostDepartmentMapper.selectByExample(DpExample);
            if (!CollectionUtils.isEmpty(departments)) {
                List<String> collect =
                        departments.stream().map(MbOrgCostDepartment::getOrgName).collect(Collectors.toList());
                costCenterPojo.setDepartments(StringUtils.join(collect, ","));
            }
        }
        return costCenterPojo;
    }

    /**
     * 获取公司下配置的所有成本中心
     *
     * @param
     * @return
     */
    @Override
    public List<CostCenter> getCostCentersByCompanyId(GetProjectInfoRequest request) {
        Example example = new Example(MbOrgCostInfo.class);
        Example.Criteria criteria = example.createCriteria();
        if (StringUtils.isNotBlank(request.getCompanyId())) {
            criteria.andEqualTo("companyId", request.getCompanyId());
        }
        criteria.andEqualTo("valid", true).andEqualTo("isDelete", false);;

        Example.Criteria criteriaStartDate = example.createCriteria();
        criteriaStartDate.andIsNull("validStartDate").orLessThanOrEqualTo("validStartDate",LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));

        Example.Criteria criteriaEndDate = example.createCriteria();
        criteriaEndDate.andIsNull("validEndDate").orGreaterThanOrEqualTo("validEndDate",LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));

        example.and(criteriaStartDate);
        example.and(criteriaEndDate);

        example.setOrderByClause("datachange_lasttime DESC");
        List<MbOrgCostInfo> costInfos = orgCostInfoMapper.selectByExample(example);
        if (StringUtils.isNotBlank(request.getQuery()) && !CollectionUtils.isEmpty(costInfos)) {
            costInfos = costInfos.stream().filter(item -> item.getCostCenterName().indexOf(request.getQuery()) > -1)
                    .collect(Collectors.toList());
        }
        return transferEntityList(costInfos);
    }

    /**
     * 根据成本中心编码获取成本中心
     *
     * @param costCenterCode
     * @return
     */
    public CostCenter getCostCenterByCode(String costCenterCode) {
        Example example = new Example(MbOrgCostInfo.class);
        example.createCriteria().andEqualTo("costCenterCode", costCenterCode).andEqualTo("isDelete", false);;
        List<MbOrgCostInfo> costInfos = orgCostInfoMapper.selectByExample(example);
        List<CostCenter> res = transferEntityList(costInfos);
        if (res.size() > 0) {
            return res.get(0);
        }
        return null;
    }

    public List<CostCenter> getCostCenterByCodeList(List<String> costCenterCodeList) {
        Example example = new Example(MbOrgCostInfo.class);
        example.createCriteria().andIn("costCenterCode", costCenterCodeList).andEqualTo("isDelete", false);;
        List<MbOrgCostInfo> mbOrgCostInfoList = orgCostInfoMapper.selectByExample(example);
        if(CollectionUtils.isEmpty(mbOrgCostInfoList)){
            return null;
        }
        return JsonUtils.parseArray(JsonUtils.toJsonString(mbOrgCostInfoList),CostCenter.class);
    }

    /**
     * 根据成本中心编码获取成本中心
     *
     * @param costCenterCodeList
     * @return
     */
    public List<CostCenter> listCostCenterByCode(Collection<String> costCenterCodeList) {
        Example example = new Example(MbOrgCostInfo.class);
        example.createCriteria().andIn("costCenterCode", costCenterCodeList).andEqualTo("isDelete", false);;
        List<MbOrgCostInfo> costInfos = orgCostInfoMapper.selectByExample(example);
        return transferEntityList(costInfos);
    }
    /**
     * 根据部门orgId 获取成本中心
     *
     * @param orgId
     * @return
     */
    @Override
    public List<CostCenter> getCostCenter(String orgId) {
        if (StringUtils.isBlank(orgId)) {
            return null;
        }

        MbOrgCostDefaultDepartment defaultDepartment = this.selectDefaultDepartmentByOrgId(orgId);
        List<CostCenter> costCenterList = new ArrayList<>();
        List<MbOrgCostInfo> mbOrgCostInfos = orgCostInfoMapper.selectByOrgId(orgId);
        for (MbOrgCostInfo mbOrgCostInfo : mbOrgCostInfos) {
            CostCenter transfer = transfer(mbOrgCostInfo);
            if (Objects.nonNull(defaultDepartment)
                    && defaultDepartment.getCostInfoId().compareTo(mbOrgCostInfo.getId()) == 0) {
                transfer.setIsDefault(Boolean.TRUE);
            } else {
                transfer.setIsDefault(Boolean.FALSE);
            }
            costCenterList.add(transfer);
        }
        return costCenterList;
    }

    @Override
    public Map<String, List<CostCenter>> getCostCenterBatch(List<String> orgIds) {
        if (CollectionUtils.isEmpty(orgIds)){
            return CollectionUtils.newHashMap();
        }
        CompletableFuture<Map<String, List<MbOrgCostDefaultDepartment>>> defaultDepartmentInfoFuture = CompletableFuture.supplyAsync(() -> selectDefaultDepartmentListByOrgIds(orgIds), getValidPassengerThreadPoolExecutor);
        CompletableFuture<List<MbOrgCostInfo>> costCenterInfoFuture = CompletableFuture.supplyAsync(() -> orgCostInfoMapper.selectByOrgIdList(orgIds), getValidPassengerThreadPoolExecutor);
        Map<String, List<MbOrgCostDefaultDepartment>> defaultDepartmentMap = CollectionUtils.newHashMap();
        List<MbOrgCostInfo> mbOrgCostInfos = CollectionUtils.newArrayList();
        try{
            defaultDepartmentMap = defaultDepartmentInfoFuture.get();
            mbOrgCostInfos = costCenterInfoFuture.get();
        } catch (Exception e){
            log.error("异步获取数据失败!", e);
        }
        if (CollectionUtils.isEmpty(mbOrgCostInfos)){
            return CollectionUtils.newHashMap();
        }
        HashMap<String, List<CostCenter>> map = new HashMap<>();
        for (MbOrgCostInfo info : mbOrgCostInfos) {
            CostCenter costCenter = transfer(info);
            MbOrgCostDefaultDepartment defaultDepartment = Optional.ofNullable(defaultDepartmentMap).map(k -> k.get(info.getOrgId())).map(k -> k.get(0)).orElse(null);
            if (Objects.nonNull(defaultDepartment)
                    && defaultDepartment.getCostInfoId().compareTo(info.getId()) == 0) {
                costCenter.setIsDefault(Boolean.TRUE);
            } else {
                costCenter.setIsDefault(Boolean.FALSE);
            }
            if (Objects.isNull(map.get(info.getOrgId()))) {
                ArrayList<CostCenter> list = new ArrayList<>();
                list.add(costCenter);
                map.put(info.getOrgId(), list);
            } else {
                map.get(info.getOrgId()).add(costCenter);
            }
        }
        return map;
    }

    /**
     * 根据部门orgId 获取成本中心
     *
     * @param orgIdList
     * @return
     */
    public List<CostCenter> listCostCenter(List<String> orgIdList) {
        if (CollectionUtils.isEmpty(orgIdList)) {
            return null;
        }
        List<MbOrgCostDefaultDepartment> defaultDepartmentList = this.selectDefaultDepartmentByOrgIds(orgIdList);
        Set<String> orgDefaultCost = defaultDepartmentList.stream().map(p->p.getOrgId()+"_"+p.getOrgId()).collect(Collectors.toSet());
        List<MbOrgCostInfo> mbOrgCostInfos = orgCostInfoMapper.selectByOrgIdList(orgIdList);
        List<CostCenter> list = new ArrayList<>();
        for (MbOrgCostInfo mbOrgCostInfo : mbOrgCostInfos) {
            CostCenter transfer = transfer(mbOrgCostInfo);
            transfer.setIsDefault(orgDefaultCost.contains(mbOrgCostInfo.getOrgId()+"_"+mbOrgCostInfo.getId()));
            list.add(transfer);
        }
        return list;
    }

    public List<CostCenter> getCostCenterNew(GetCostCenterListRequest request) {
        MbOrgCostDefaultDepartment defaultDepartment = this.selectDefaultDepartmentByOrgId(request.getOrgId());
        List<CostCenter> costCenterList = new ArrayList<>();
        List<MbOrgCostInfo> mbOrgCostInfos = orgCostInfoMapper.selectByOrgId(request.getOrgId());
        for (MbOrgCostInfo mbOrgCostInfo : mbOrgCostInfos) {
            CostCenter transfer = transfer(mbOrgCostInfo);
            if (Objects.nonNull(defaultDepartment)
                    && defaultDepartment.getCostInfoId().compareTo(mbOrgCostInfo.getId()) == 0) {
                transfer.setIsDefault(Boolean.TRUE);
            } else {
                transfer.setIsDefault(Boolean.FALSE);
            }
            costCenterList.add(transfer);
        }

        if (StringUtils.isNotBlank(request.getQuery())) {
            costCenterList =
                    costCenterList.stream().filter(item -> item.getCostCenterName().indexOf(request.getQuery()) > -1)
                            .collect(Collectors.toList());
        }

        return costCenterList;
    }

    /**
     * 实体转换
     *
     * @param model
     * @return
     */
    private MbOrgCostInfo transfer(CostCenter model) {
        MbOrgCostInfo costInfo = new MbOrgCostInfo();
        costInfo.setId(model.getId());
        costInfo.setCompany(model.getCompany());
        costInfo.setCompanyId(model.getCompanyId());
        costInfo.setCostCenterCode(model.getCostCenterCode());
        costInfo.setCostCenterName(model.getCostCenterName());
        costInfo.setValid(model.getValid());
        try {
            SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd");
            Date d2 = sdf2.parse(model.getCreateDate());
            costInfo.setCreateDate(d2);
        } catch (Exception E) {

        }

        costInfo.setIsDelete(false);
        costInfo.setOperatorUid(model.getUid());
        costInfo.setOperatorName(model.getUserName());
        if (Objects.isNull(model.getCreateDate())){
            costInfo.setCreateDate(model.getValidStartDate());
        }
        costInfo.setValidStartDate(model.getValidStartDate());
        costInfo.setValidEndDate(model.getValidEndDate());
        return costInfo;
    }

    /**
     * 实体转换
     *
     * @param model
     * @return
     */
    private CostCenter transfer(MbOrgCostInfo model) {
        CostCenter costInfo = new CostCenter();
        if (model.getId() != null && model.getId() > 0) {
            costInfo.setId(model.getId());
        }
        costInfo.setCompany(model.getCompany());
        costInfo.setCompanyId(model.getCompanyId());
        costInfo.setCostCenterCode(model.getCostCenterCode());
        costInfo.setCostCenterName(model.getCostCenterName());
        costInfo.setCostCenterNameAndCode(model.getCostCenterName()+"/"+model.getCostCenterCode());
        costInfo.setValid(model.getValid());
        if (model.getCreateDate() != null) {
            costInfo.setCreateDate(new SimpleDateFormat(DateUtil.DF_YMD).format(model.getCreateDate()));
        }
        costInfo.setValidStartDate(model.getValidStartDate());
        costInfo.setValidEndDate(model.getValidEndDate());
        costInfo.setUid(model.getOperatorUid());
        costInfo.setUserName(model.getOperatorName());
        costInfo.setLastUpdateTime(model.getUpdateTime());
        costInfo.setCostCenterId(Optional.ofNullable(model.getId()).map(String::valueOf).orElse(""));
        return costInfo;
    }

    /**
     * 实体转换，并做子查询
     *
     * @param costInfos
     * @return
     */
    private List<CostCenter> transferEntityList(List<MbOrgCostInfo> costInfos) {
        List<CostCenter> costCenterList = Lists.newArrayList();

        for (MbOrgCostInfo info : costInfos) {
            CostCenter item = transfer(info);
            Example DpExample = new Example(MbOrgCostDepartment.class);
            DpExample.createCriteria().andEqualTo("costInfoId", info.getId());

            List<MbOrgCostDepartment> departments = orgCostDepartmentMapper.selectByExample(DpExample);
            List<OrgInfo> orgInfos = new ArrayList<>();
            for (MbOrgCostDepartment dp : departments) {
                OrgInfo orgInfo = new OrgInfo();
                orgInfo.setName(dp.getOrgName());
                orgInfo.setOrgId(dp.getOrgId());
                orgInfos.add(orgInfo);
            }
            item.setDepartments(orgInfos);
            costCenterList.add(item);
        }
        return costCenterList;
    }

    /**
     * 获取子公司下所有部门,已配置的添加标签
     */
    public List<GetOrgTreeRsp> getOrgTree(GetDepartmentsRequest request) {
        List<GetOrgTreeRsp> result = new ArrayList<>();

        List<String> selectList = request.getDepartments();
        List<GetOrgTreeRsp> orgTreeList = new ArrayList<>();
        // 查询全集团数据
        if(WholeGroupQueryEnum.APPROVE.getCode().equals(request.getWholeGroupQuery())
                && organizationApollo.enableApproveShowAllOrg()){
            orgTreeList  = organizationInfoService.getOrgTreeWhole();
        }else{//查询单组织数据
            GetOrgTreeRsp orgTree = organizationInfoService
                    .getOrgTree(new GetOrgTreeRequest(request.getOrgId(), request.getIsSelectUser()));
            orgTreeList.add(orgTree);
        }
        // orgTreeList根据ID去重
        orgTreeList = new ArrayList<>(orgTreeList.stream()
                .collect(Collectors.toMap(GetOrgTreeRsp::getId, obj -> obj, (obj1, obj2) -> obj1))
                .values());
        for (GetOrgTreeRsp getOrgTreeRsp : orgTreeList) {
            GetOrgTreeRsp orgTree = getGetOrgTreeRsp(getOrgTreeRsp,request, selectList);
            result.add(orgTree);
        }

        return result;
    }

    private GetOrgTreeRsp getGetOrgTreeRsp(GetOrgTreeRsp orgTree,GetDepartmentsRequest request, List<String> selectList) {
        // 查询组织树
//        GetOrgTreeRsp orgTree = organizationInfoService
//                .getOrgTree(new GetOrgTreeRequest(request.getOrgId(), request.getIsSelectUser()));
        if ("T".equals(orgTree.getValid())) {
            orgTree.setValid("F");
        } else {
            orgTree.setValid("T");
        }

        if (selectList.contains(orgTree.getOrgId())) {
            orgTree.setAdd("T");
        } else {
            orgTree.setAdd("F");
        }

        Map<String, MbOrgCostDefaultDepartment> defaultDepartmentMap = new HashMap<>();
        if (Objects.nonNull(request.getId()) && request.getId() > 0) {
            List<MbOrgCostDefaultDepartment> defaultDepartments = this.selectDefaultDepartmentByCostId(request.getId());
            defaultDepartments.forEach(item -> {
                defaultDepartmentMap.put(item.getOrgId(), item);
            });
        }

        if (Objects.nonNull(defaultDepartmentMap.get(orgTree.getOrgId()))) {
            orgTree.setIsDefault(true);
        } else {
            orgTree.setIsDefault(false);
        }

        for (GetOrgTreeRsp childrenTree : orgTree.getChildren()) {
            addDepartmentTag(childrenTree, selectList, defaultDepartmentMap);
        }
        return orgTree;
    }

    /**
     * 获取该子公司下所有成本中心已经配置过的部门
     *
     * @param
     * @return List<String>
     */
    public List<String> getDepartments(String companyId) {
        return orgCostInfoMapper.selectDepartmentByCompanyId(companyId);
    }

    /**
     * 获取子公司下所有部门,给已经配置的添加标签
     *
     * @param orgTree
     * @param selectList
     */
    public void addDepartmentTag(GetOrgTreeRsp orgTree, List<String> selectList,
            Map<String, MbOrgCostDefaultDepartment> defaultDepartmentMap) {
        if ("T".equals(orgTree.getValid())) {
            orgTree.setValid("F");
        } else {
            orgTree.setValid("T");
        }

        if (selectList.contains(orgTree.getOrgId())) {
            orgTree.setAdd("T");
        } else {
            orgTree.setAdd("F");
        }

        if (Objects.nonNull(defaultDepartmentMap.get(orgTree.getOrgId()))) {
            orgTree.setIsDefault(true);
        } else {
            orgTree.setIsDefault(false);
        }

        if (!CollectionUtils.isEmpty(orgTree.getChildren())) {
            orgTree.getChildren().stream().filter(e -> Objects.nonNull(e)).forEach(
                    e -> {
                        addDepartmentTag(e, selectList, defaultDepartmentMap);
                    });
        }
    }

    /**
     * 复制属性，list不可以复制，因为类型不同
     *
     * @param orgTree
     * @param departTree
     * @return void
     */
    private void copyProperties(GetOrgTreeResponse orgTree, GetDepartTreeResponse departTree) {
        departTree.setId(orgTree.getId());
        departTree.setOrgId(orgTree.getOrgId());
        departTree.setLabel(orgTree.getLabel());
        departTree.setLevel(orgTree.getLevel());
        departTree.setValid(orgTree.getValid());
        departTree.setPid(orgTree.getPid());
        departTree.setType(orgTree.getType());
    }

    /**
     * 产线下单的时候需要查询成本中心
     *
     * @param saveOrderRequest
     * @return
     */
    public List<BaseKeyValue> getCostCenterForSaveOrder(SaveOrderCostCenterRequest saveOrderRequest) {
        String applyNo = saveOrderRequest.getApplyTripNo();
        String orderUid = saveOrderRequest.getUid();
        List<Passenger> passengerList = saveOrderRequest.getPassengerList();
        List<String> uids = new ArrayList<>();
        List<String> tempUids = new ArrayList<>();
        if (!CollectionUtils.isEmpty(passengerList)) {
            for (Passenger passenger : passengerList) {
                if (saveOrderRequest.getUid().equals(passenger.getUid())
                        && !tempUids.contains(saveOrderRequest.getUid())) {
                    tempUids.add(saveOrderRequest.getUid());
                }
                if (!StringUtils.isBlank(passenger.getUid())) {
                    if (!uids.contains(passenger.getUid())) {
                        uids.add(passenger.getUid());
                    }
                } else {
                    if (!uids.contains(saveOrderRequest.getUid())) {
                        uids.add(saveOrderRequest.getUid());
                    }
                    tempUids.add(passenger.getNoEmployeeId());
                }
            }
        } else {
            uids.add(saveOrderRequest.getUid());
            tempUids.add(saveOrderRequest.getUid());
        }
        List<BaseKeyValue> result = new ArrayList<>();
        JSONResult<Map<String, OrgInfoVo>> orgMapResult = organizationService.listByUids(uids);
        // 有出差申请单
        if (!StringUtils.isBlank(applyNo)) {
            // 查询出差申请单
            ApplyTripDetailResponse applyTripDetailResponse = applyTripClientLoader.getApplyTripDetail(applyNo);
            if (applyTripDetailResponse != null) {
                List<ApplyTripCostCenterResponse> applyTripCostCenterResponseList =
                        applyTripDetailResponse.getCostCenterList();
                Map<String, ApplyTripCostCenterResponse> costCenterMap =
                        applyTripCostCenterResponseList.stream()
                                .collect(Collectors.toMap(x -> x.getUid(), x -> x, (k1, k2) -> k1));
                ApplyTripCostCenterResponse applyTripCostCenterResponse = null;
                for (String uid : uids) {
                    if (uid.equals(orderUid)) {
                        applyTripCostCenterResponse = costCenterMap.get(uid);
                        for (String tempUid : tempUids) {
                            if (applyTripCostCenterResponse != null) {
                                costCenterBaseValue(tempUid, applyTripCostCenterResponse.getCostCenterCode(),
                                        applyTripCostCenterResponse.getCostCenterName(), result);
                            }
                        }
                    } else {
                        applyTripCostCenterResponse = costCenterMap.get(uid);
                        if (applyTripCostCenterResponse != null) {
                            costCenterBaseValue(uid, applyTripCostCenterResponse.getCostCenterCode(),
                                    applyTripCostCenterResponse.getCostCenterName(), result);
                        }
                    }
                }
            }
        }
        // 无出差申请单
        if (orgMapResult.isSUCCESS()) {
            CostCenter costCenter = null;
            Map<String, OrgInfoVo> orgMap = orgMapResult.getData();
            if (orgMap != null) {
                for (String uid : uids) {
                    OrgInfoVo orgInfoVo = orgMap.get(uid);
                    List<CostCenter> costCenters = getCostCenter(orgInfoVo.getOrgId());
                    if (CollectionUtils.isNotEmpty(costCenters)) {
                        costCenter = costCenters.get(0);
                    }
                    if (costCenter != null && StringUtils.isBlank(applyNo)) {
                        if (uid.equals(orderUid)) {
                            for (String tempUid : tempUids) {
                                costCenterBaseValue(tempUid, costCenter.getCostCenterCode(),
                                        costCenter.getCostCenterName(), result);
                            }
                        } else {
                            costCenterBaseValue(uid, costCenter.getCostCenterCode(), costCenter.getCostCenterName(),
                                    result);
                        }
                    }
                    if (uid.equals(orderUid)) {
                        for (String tempUid : tempUids) {
                            departmentBaseValue(tempUid, orgInfoVo.getOrgId(), orgInfoVo.getName(), result);
                        }
                    } else {
                        departmentBaseValue(uid, orgInfoVo.getOrgId(), orgInfoVo.getName(), result);
                    }
                }
            }
        }
        return result;
    }

    private List<BaseKeyValue> costCenterBaseValue(String uid, String costCenterCode, String costCenterName,
            List<BaseKeyValue> result) {
        BaseKeyValue baseKeyValue = new BaseKeyValue();
        BaseKeyValue baseKeyValueT = new BaseKeyValue();
        baseKeyValue.setUid(uid);
        baseKeyValue.setKey(CostCenterConstant.COSTCENTERID);
        baseKeyValue.setValue(costCenterCode);
        baseKeyValueT.setUid(uid);
        baseKeyValueT.setKey(CostCenterConstant.COSTCENTERNAME);
        baseKeyValueT.setValue(costCenterName);
        result.add(baseKeyValue);
        result.add(baseKeyValueT);
        return result;
    }

    private List<BaseKeyValue> departmentBaseValue(String uid, String departmentId, String departmentName,
            List<BaseKeyValue> result) {
        BaseKeyValue baseKeyValue = new BaseKeyValue();
        BaseKeyValue baseKeyValueT = new BaseKeyValue();
        baseKeyValue.setUid(uid);
        baseKeyValue.setKey(CostCenterConstant.DEPARTMENTID);
        baseKeyValue.setValue(departmentId);
        baseKeyValueT.setUid(uid);
        baseKeyValueT.setKey(CostCenterConstant.DEPARTMENTNAME);
        baseKeyValueT.setValue(departmentName);
        result.add(baseKeyValueT);
        result.add(baseKeyValue);
        return result;
    }

    /**
     * 调用日志接口中的参数配置格式化
     *
     * @param newCenter oldCenter operationType
     * @return List<OperateLogContentDataVo>
     */
    public List<OperateLogContentDataVo> getContentList(CostCenter newCenter, CostCenter oldCenter,
            String operationType) throws InvocationTargetException, IllegalAccessException {

        Map<String, Method> methodMap = new HashMap<>();
        Method[] methods = CostCenter.class.getDeclaredMethods();
        for (Method method : methods) {
            if (method.getName().startsWith("get")) {
                methodMap.put(method.getName(), method);
            }
        }
        List<OperateLogContentDataVo> contentList = new ArrayList<OperateLogContentDataVo>();
        Field[] fields = CostCenter.class.getDeclaredFields();
        if (fields != null) {
            for (Field field : fields) {
                if (!field.isAccessible()) {
                    field.setAccessible(true);
                }
                if (field.getAnnotation(FieldDescription.class) == null) {
                    continue;
                }
                String fieldDescription = field.getAnnotation(FieldDescription.class).value();
                String fieldName = "get" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1);
                Method methd = methodMap.get(fieldName);
                if (methd.getReturnType().equals(List.class)) {
                    StringBuilder newValue = new StringBuilder();
                    StringBuilder oldValue = new StringBuilder();
                    List<OrgInfo> newDepartments =
                            methd.invoke(newCenter) == null ? null : (List<OrgInfo>)methd.invoke(newCenter);
                    List<OrgInfo> oldDepartments =
                            methd.invoke(oldCenter) == null ? null : (List<OrgInfo>)methd.invoke(oldCenter);
                    if (!CollectionUtils.isEmpty(newDepartments)) {
                        for (OrgInfo orgInfo : newDepartments) {
                            newValue.append(orgInfo.getName() + "、");
                        }
                    }
                    if (!CollectionUtils.isEmpty(oldDepartments)) {
                        for (OrgInfo orgInfo : oldDepartments) {
                            oldValue.append(orgInfo.getName() + "、");
                        }
                    }
                    if (newValue.length() > 0) {
                        newValue.deleteCharAt(newValue.length() - 1);
                    }
                    if (oldValue.length() > 0) {
                        oldValue.deleteCharAt(oldValue.length() - 1);
                    }
                    if (!newValue.toString().equals(oldValue.toString())) {
                        OperateLogContentDataVo content = new OperateLogContentDataVo();
                        content.setField(fieldDescription);
                        content.setNewValue(CollectionUtils.isEmpty(newDepartments) ? null : newValue.toString());
                        content.setOldValue(CollectionUtils.isEmpty(oldDepartments) ? null : oldValue.toString());
                        content.setOperationType(operationType);
                        contentList.add(content);
                    }
                    continue;
                }

                String newValue = methd.invoke(newCenter) == null ? "" : methd.invoke(newCenter).toString();
                String oldValue = methd.invoke(oldCenter) == null ? "" : methd.invoke(oldCenter).toString();
                if (!newValue.equals(oldValue)) {
                    OperateLogContentDataVo content = new OperateLogContentDataVo();
                    content.setField(fieldDescription);
                    content.setNewValue(methd.invoke(newCenter) == null ? null : methd.invoke(newCenter).toString());
                    content.setOldValue(methd.invoke(oldCenter) == null ? null : methd.invoke(oldCenter).toString());
                    content.setOperationType(operationType);
                    contentList.add(content);
                }
            }
        }
        return contentList;
    }

    public boolean deleteByOrgId(String orgId) {
        if (StringUtils.isBlank(orgId)) {
            return false;
        }
        // 查询组织下的成本中心
        List<MbOrgCostInfo> costInfoList = orgCostInfoMapper.selectByCompanyId(orgId);
        // 只有公司下才会有成本中心，组织只能关联成本中心
        if (!CollectionUtils.isEmpty(costInfoList)) {
            // 删除所有成本中心和成本中心关联关系
            costInfoList.forEach(e -> {
                int count = orgCostInfoMapper.deleteByPrimaryKey(e.getId());
                if (count > 0) {
                    // 先删除原有数据
                    Example example = new Example(MbOrgCostDepartment.class);
                    example.createCriteria().andEqualTo("costInfoId", e.getId());
                    orgCostDepartmentMapper.deleteByExample(example);

                    // 删除该组织的默认成本中心是当前成本中心的关系
                    Example exampleDefault = new Example(MbOrgCostDefaultDepartment.class);
                    exampleDefault.createCriteria().andEqualTo("costInfoId", e.getId());
                    mbOrgCostDefaultDepartmentMapper.deleteByExample(exampleDefault);
                }
            });
        } else {
            // 删除该组织和成本中心的关系
            Example example = new Example(MbOrgCostDepartment.class);
            example.createCriteria().andEqualTo("orgId", orgId);
            orgCostDepartmentMapper.deleteByExample(example);

            // 删除该组织和默认成本中心的关系
            Example exampleDefault = new Example(MbOrgCostDefaultDepartment.class);
            exampleDefault.createCriteria().andEqualTo("orgId", orgId);
            mbOrgCostDefaultDepartmentMapper.deleteByExample(exampleDefault);
        }
        return true;
    }

    public String syncCostInfoExcel(MultipartFile file, CostCenterExcelVo requestVo) {
        try {
            if (file == null) {
                throw new CorpBusinessException(ExceptionCodeEnum.Alert, "上传文件为空");
            }
            if (!file.getOriginalFilename().endsWith(".xls") && !file.getOriginalFilename().endsWith(".xlsx")) {
                throw new CorpBusinessException(ExceptionCodeEnum.Alert, "文件格式必须为xls或xlsx");
            }

            Workbook workbook = null;

            if (file.getOriginalFilename().endsWith(".xls")) {
                workbook = new HSSFWorkbook(file.getInputStream());
            } else if (file.getOriginalFilename().endsWith(".xlsx")) {
                workbook = new XSSFWorkbook(file.getInputStream());
            }

            // 取出第一页
            Sheet sheet = workbook.getSheetAt(0);
            // Excel内容
            List<CostCenterExcelColumnVo> beanListFromExcel =
                    excelUtils.getBeanListFromExcelTwo(sheet, CostCenterExcelColumnVo.class);

            beanListFromExcel.forEach(t ->  ObjectStringTrimUtils.allFieldRemoveWarp(t));
            // 本次任务号
            String taskNo = UuidUtil.getUUid();
            // 校验数据
            CostCenterUploadExcelInfo uploadExcelInfo =
                    this.checkExcelInfo(beanListFromExcel, requestVo.getCorpId(), taskNo);
            // 组织数据
            CostCenterExcelInsertBo assembleInfo =
                    this.assembleInfo(uploadExcelInfo, requestVo, file.getOriginalFilename(), taskNo);
            MbOrgCostUpload costUpload = assembleInfo.getCostUpload();
            if(costUpload.getFiledNumber() > 0){
                assembleInfo.setMessage(String.format("上传%d条，其中校验未通过%d条，校验失败会全部回滚", costUpload.getSuccessNumber() + costUpload.getFiledNumber(),
                        costUpload.getFiledNumber()));
                // 查询入上传记录表
                mbOrgCostUploadMapper.insert(assembleInfo.getCostUpload());
                if (!CollectionUtils.isEmpty(assembleInfo.getCostUploadDetails())) {
                    mbOrgCostUploadDetailMapper.insertList(assembleInfo.getCostUploadDetails());
                }
                return assembleInfo.getMessage();
            }


            // 查询入上传记录表
            mbOrgCostUploadMapper.insert(assembleInfo.getCostUpload());

            // 数据入库
            saveToDb(assembleInfo);
            return assembleInfo.getMessage();
        } catch (Exception e) {
            log.error("上传成本中心异常:{}", e.getMessage(), e);
            return "上传失败";
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public void saveToDb(CostCenterExcelInsertBo assembleInfo) {
        if (!CollectionUtils.isEmpty(assembleInfo.getCostUploadDetails())) {
            mbOrgCostUploadDetailMapper.insertList(assembleInfo.getCostUploadDetails());
        }

        if (!CollectionUtils.isEmpty(assembleInfo.getCostInfos())) {
            for (MbOrgCostInfo costInfo : assembleInfo.getCostInfos()) {

                Example example = new Example(MbOrgCostInfo.class);
                example.createCriteria().andEqualTo("companyId", costInfo.getCompanyId())
                        .andEqualTo("costCenterCode", costInfo.getCostCenterCode())
                        .andEqualTo("isDelete", false);
                List<MbOrgCostInfo> costInfoList = orgCostInfoMapper.selectByExample(example);
                if (CollectionUtils.isNotEmpty(costInfoList)) {
                    costInfoList.forEach(e -> {
                        costInfo.setId(e.getId());
                        orgCostInfoMapper.updateByPrimaryKey(costInfo);

                        MbOrgCostDepartment department = new MbOrgCostDepartment();
                        department.setCostInfoId(e.getId());
                        orgCostDepartmentMapper.delete(department);
                    });
                } else {
                    orgCostInfoMapper.insert(costInfo);
                }
            }
            // orgCostInfoMapper.insertList(assembleInfo.getCostInfos());

            List<MbOrgCostDepartment> departmentList = new ArrayList<>();
            assembleInfo.getCostInfos().forEach(e -> {
                e.getDepartmentList().forEach(v -> v.setCostInfoId(e.getId()));
                departmentList.addAll(e.getDepartmentList());
            });
            if(CollectionUtils.isNotEmpty(departmentList)){
                orgCostDepartmentMapper.insertList(departmentList);
            }

        }
    }

    public CostCenterExcelInsertBo assembleInfo(CostCenterUploadExcelInfo uploadExcelInfo, CostCenterExcelVo requestVo,
            String fileName, String taskNo) {
        CostCenterExcelInsertBo result = new CostCenterExcelInsertBo();
        List<MbOrgCostUploadDetail> uploadDetailList = new ArrayList<>();
        List<MbOrgCostInfo> costInfoList = new ArrayList<>();
        Integer successNumber = 0;
        Integer filedNumber = 0;

        for (CostCenterUploadExcelInfo.CostCenterUploadDetailBo uploadInfo : uploadExcelInfo.getDetailBos()) {
            if (StringUtils.isNotBlank(uploadInfo.getFiledReason())) {
                MbOrgCostUploadDetail uploadDetail = new MbOrgCostUploadDetail();
                uploadDetail.setTaskNo(uploadInfo.getTaskNo());
                uploadDetail.setCostCenterCode(uploadInfo.getCostCenterCode());
                uploadDetail.setCostCenterName(uploadInfo.getCostCenterName());
                uploadDetail.setFiledReason(uploadInfo.getFiledReason());
                uploadDetail.setCreateDate(uploadInfo.getCreateDate());
                uploadDetail.setValidStartDate(uploadInfo.getValidStartDate());
                uploadDetail.setValidEndDate(uploadInfo.getValidEndDate());
                uploadDetail.setLine(uploadInfo.getLine());
                uploadDetail.setOrgId(uploadInfo.getBusinessCode());
                uploadDetailList.add(uploadDetail);
                filedNumber++;
            } else {
                MbOrgInfo corpInfo = organizationInfoService.findByBusinessCode(uploadInfo.getBusinessCode());
                MbOrgCostInfo costInfo = new MbOrgCostInfo();
                costInfo.setCompanyId(corpInfo.getOrgId());
                costInfo.setCompany(corpInfo.getName());
                if (StringUtils.isNotBlank(uploadInfo.getCreateDate())) {
                    costInfo.setCreateDate(
                            cn.hutool.core.date.DateUtil.parse(uploadInfo.getCreateDate(), "yyyy-MM-dd"));
                }
                costInfo.setUpdateTime(new Date());
                costInfo.setCreateTime(new Date());
                costInfo.setValidStartDate(uploadInfo.getValidStartDate());
                costInfo.setValidEndDate(uploadInfo.getValidEndDate());
                costInfo.setCostCenterCode(uploadInfo.getCostCenterCode());
                costInfo.setCostCenterName(uploadInfo.getCostCenterName());
                costInfo.setValid(Boolean.TRUE);
                costInfo.setIsDelete(false);
                costInfo.setOperatorUid(requestVo.getUid());
                costInfo.setOperatorName(requestVo.getUserName());
                costInfo.setTaskNo(uploadInfo.getTaskNo());

                List<MbOrgCostDepartment> departments = new ArrayList<>();
                // 适用部门
                List<String> applicationDepartmentList = uploadInfo.getApplicationDepartmentList();
                for (int i = 0; i < applicationDepartmentList.size(); i++) {
                    String bussinessCode = applicationDepartmentList.get(i);
                    MbOrgCostDepartment department = new MbOrgCostDepartment();
                    List<MbOrgInfo> mbOrgInfos = uploadExcelInfo.getOrgIdGroupMap().get(bussinessCode);
                    department.setOrgName(mbOrgInfos.get(0).getName());
                    department.setOrgId(mbOrgInfos.get(0).getOrgId());
                    department.setCreateTime(new Date());
                    department.setUpdateTime(new Date());
                    departments.add(department);
                }
              /*  String[] orgIdArr = uploadInfo.getOrgId().split(",");
                Arrays.stream(orgIdArr).forEach(orgId -> {
                    MbOrgCostDepartment department = new MbOrgCostDepartment();
                    department.setOrgId(orgId);
                    List<MbOrgInfo> mbOrgInfos = uploadExcelInfo.getOrgIdGroupMap().get(orgId);
                    department.setOrgName(mbOrgInfos.get(0).getName());
                    department.setCreateTime(new Date());
                    department.setUpdateTime(new Date());
                    departments.add(department);
                });*/
                costInfo.setDepartmentList(departments);
                costInfoList.add(costInfo);
                successNumber++;
            }
        }

        MbOrgCostUpload costUpload = new MbOrgCostUpload();
        costUpload.setTaskNo(taskNo);
        costUpload.setFileName(fileName);
        costUpload.setCreateDate(new Date());
        costUpload.setSuccessNumber(successNumber);
        costUpload.setFiledNumber(filedNumber);
        costUpload.setOperatorName(requestVo.getUserName());
        costUpload.setCompanyId(requestVo.getCorpId());

        result.setCostInfos(costInfoList);
        result.setCostUploadDetails(uploadDetailList);
        result.setCostUpload(costUpload);
        result.setMessage(String.format("上传%d条，失败%d条", costUpload.getSuccessNumber() + costUpload.getFiledNumber(),
                costUpload.getFiledNumber()));
        return result;

    }

    public CostCenterUploadExcelInfo checkExcelInfo(List<CostCenterExcelColumnVo> beanListFromExcel, String corpId,
            String taskNo) {
        CostCenterUploadExcelInfo uploadExcelInfo = new CostCenterUploadExcelInfo();
        List<CostCenterUploadExcelInfo.CostCenterUploadDetailBo> uploadDetailBoList = new ArrayList<>();
        DateTime currentTime = new DateTime();
        for (CostCenterExcelColumnVo columnInfo : beanListFromExcel) {
            StringBuilder errorLog = new StringBuilder();
            // 清除空格
            StrUtils.fieldRemoveSpace(columnInfo);
            if (StringUtils.isBlank(columnInfo.getBusinessCode())) {
                errorLog.append("公司/部门编码为空;");
            }
            if (StringUtils.isBlank(columnInfo.getCostCenterName())) {
                errorLog.append("成本中心名称为空;");
            }
            if (StringUtils.isBlank(columnInfo.getCostCenterCode())) {
                errorLog.append("成本中心编码为空;");
            }
            // 成本中心生效开始时间，成本中心生效结束时间规则：
            // 输入格式为：yyyy-MM-dd HH:mm:ss，例如：2023-10-01 12:23:00
            // 两者都不输入，为立即生效，开始时间为当前时间、结束时间为2123-01-01 00:00:00；
            // 两者都输入，开始时间必须大于当前时间，结束时间必须大于开始时间；
            // 只填写开始时间，结束默认值为 2123-01-01 00:00:00；
            // 只填写结束时间，开始时间默认值为当前系统时间；
            DateTime validStartDate = currentTime;
            DateTime validEndDate =  currentTime;
            try {
                validStartDate = StrUtil.isBlank(columnInfo.getValidStartDate()) ? currentTime :
                        cn.hutool.core.date.DateUtil.parse(columnInfo.getValidStartDate(), DatePattern.NORM_DATETIME_FORMAT);
            } catch (Exception e) {
                errorLog.append("成本生效开始时间日期格式不正确;");
            }
            try {
                validEndDate = StrUtil.isBlank(columnInfo.getValidEndDate()) ?
                        cn.hutool.core.date.DateUtil.parse("2123-01-01 00:00:00", DatePattern.NORM_DATETIME_FORMAT):
                        cn.hutool.core.date.DateUtil.parse(columnInfo.getValidEndDate(), DatePattern.NORM_DATETIME_FORMAT);
            } catch (Exception e) {
                errorLog.append("成本生效结束时间日期格式不正确;");
            }

            if(validStartDate.isBefore(currentTime)){
                errorLog.append("成本中心生效开始时间必须大于当前时间;");
            }
            if(validEndDate.isBefore(currentTime)){
                errorLog.append("成本中心失效结束时间必须大于当前时间;");
            }
            if(validEndDate.before(validStartDate)){
                errorLog.append("成本中心失效结束时间必须大于开始时间;");
            }

            CostCenterUploadExcelInfo.CostCenterUploadDetailBo uploadDetailBo =
                    new CostCenterUploadExcelInfo.CostCenterUploadDetailBo();
            uploadDetailBo.setLine(Integer.valueOf(columnInfo.getLineNo()));
            uploadDetailBo.setCostCenterCode(columnInfo.getCostCenterCode());
            uploadDetailBo.setCostCenterName(columnInfo.getCostCenterName());
            uploadDetailBo.setValidStartDate(validStartDate);
            uploadDetailBo.setValidEndDate(validEndDate);
            uploadDetailBo.setApplicationDepartmentList(Collections.EMPTY_LIST);
            String applicationDepartment = columnInfo.getApplicationDepartment();
            if (applicationDepartment != null && !applicationDepartment.isEmpty()) {
                String[] arrayAppDepart = Pattern.compile("[;；]").split(applicationDepartment);
                List<String> applicationDepartmentList = new ArrayList<>(Arrays.asList(arrayAppDepart));
                uploadDetailBo.setApplicationDepartmentList(applicationDepartmentList);
            }
            uploadDetailBo.setFiledReason(errorLog.toString());
            uploadDetailBo.setBusinessCode(columnInfo.getBusinessCode());
            uploadDetailBo.setTaskNo(taskNo);
            uploadDetailBoList.add(uploadDetailBo);
        }

        // 按成本中心编码聚合
        Map<String, List<CostCenterUploadExcelInfo.CostCenterUploadDetailBo>> costCenterCodeMap =
                uploadDetailBoList.stream().filter(item -> StringUtils.isNotBlank(item.getCostCenterCode())).collect(
                        Collectors.groupingBy(CostCenterUploadExcelInfo.CostCenterUploadDetailBo::getCostCenterCode));
        // 查询成本中心

        List<String> businessCodes = beanListFromExcel.stream().filter(f-> StringUtils.isNotBlank(f.getBusinessCode())).map(CostCenterExcelColumnVo::getBusinessCode).collect(Collectors.toList());
        List<MbOrgInfo> mbOrgInfos = organizationInfoService.listCompanyByBusinessCodes(businessCodes);

        List<String> orgIdDataPermissions = (List<String>) RequestContext.getCurrentContext().getContextParams(DATA_PERMISSION_ORG_ID_LIST);


        Map<String, List<MbOrgInfo>> businessCodeGroupMap =
                mbOrgInfos.stream().filter(a -> StringUtils.isNotBlank(a.getBusinessCode()))
                        .collect(Collectors.groupingBy(MbOrgInfo::getBusinessCode));

        Map<String, List<MbOrgInfo>> businessCodeAndNameGroupMap = new HashMap<>();


        uploadDetailBoList.forEach(item -> {
            StringBuilder errorLog = new StringBuilder().append(item.getFiledReason());
            List<MbOrgInfo> departmentOrgInfos = new ArrayList<>();
            if (costCenterCodeMap.get(item.getCostCenterCode()) != null
                    && costCenterCodeMap.get(item.getCostCenterCode()).size() > 1) {
                errorLog.append("Excel中存在相同的成本中心编码;");
            }

            if (!businessCodeGroupMap.containsKey(item.getBusinessCode())) {
                errorLog.append(item.getBusinessCode() + "公司或部门不存在;");
            }else {
                MbOrgInfo mbOrgInfo = businessCodeGroupMap.get(item.getBusinessCode()).get(0);
                if ("F".equals(mbOrgInfo.getValid())) {
                    errorLog.append("公司或部门状态无效;");
                }
                // 校验数据权限
                if(CollectionUtils.isNotEmpty(orgIdDataPermissions) && !orgIdDataPermissions.contains(mbOrgInfo.getOrgId())){
                    errorLog.append("公司不在数据权限范围内;");
                }
                departmentOrgInfos = organizationInfoService.listAllDepartments(mbOrgInfo.getOrgId(), false);
            }
            
            businessCodeAndNameGroupMap.putAll( departmentOrgInfos.stream().filter(a -> StringUtils.isNotBlank(a.getName()))
                    .collect(Collectors.groupingBy(t -> (Optional.ofNullable(t.getName()).orElse("").concat("/").concat(Optional.ofNullable(t.getBusinessCode()).orElse(""))))));

            checkDepartBusinessCode(businessCodeAndNameGroupMap, item,errorLog);
            if(StringUtils.isNotBlank(errorLog)){
                item.setFiledReason(errorLog.toString());
            }
        });
        uploadExcelInfo.setDetailBos(uploadDetailBoList);
        uploadExcelInfo.setOrgIdGroupMap(businessCodeAndNameGroupMap);
        return uploadExcelInfo;
    }

    private void checkDepartBusinessCode(Map<String, List<MbOrgInfo>> businessCodeAndNameGroupMap, CostCenterUploadExcelInfo.CostCenterUploadDetailBo item,StringBuilder errorLog) {
        for (int i = 0; i < item.getApplicationDepartmentList().size(); i++) {
            String departBusinessCodeAndName = item.getApplicationDepartmentList().get(i);
            if(StringUtils.isBlank(departBusinessCodeAndName)){
                continue;
            }
            if(!departBusinessCodeAndName.contains("/")){
                errorLog.append("适用部门格式不正确;");
            }
            if(CollectionUtils.isEmpty(businessCodeAndNameGroupMap)){
                continue;
            }
            if (!businessCodeAndNameGroupMap.containsKey(departBusinessCodeAndName)) {
                errorLog.append("适用部门需为项目所属公司下属部门;");
            }else {
                List<MbOrgInfo> mbOrgInfoList =  businessCodeAndNameGroupMap.get(item.getBusinessCode());
                if(CollectionUtils.isEmpty(mbOrgInfoList)){
                    continue;
                }
                MbOrgInfo mbOrgInfo = mbOrgInfoList.get(0);
                String key = Optional.ofNullable(mbOrgInfo.getName()).orElse("").concat("/").concat(Optional.ofNullable(mbOrgInfo.getBusinessCode()).orElse(""));
                if(!departBusinessCodeAndName.equals(key)){
                    errorLog.append("适用部门需为项目所属公司下属部门;");
                }
            }
        }
    }

    public List<MbOrgCostDepartment> getCostDepartmentList(Set<Integer> costInfoIds) {
        if (CollectionUtils.isEmpty(costInfoIds)) {
            return Collections.emptyList();
        }
        Example example = new Example(MbOrgCostDepartment.class);
        example.createCriteria().andIn("costInfoId", costInfoIds);
        List<MbOrgCostDepartment> mbOrgCostDepartments = orgCostDepartmentMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(mbOrgCostDepartments)) {
            return Collections.emptyList();
        }
        return mbOrgCostDepartments;
    }

    public CostUploadInfoPageResponseVo selectUploadInfoPage(CostUploadInfoPageRequestVo requestVo) {
        Example example = new Example(MbOrgCostUpload.class);
        Example.Criteria criteria = example.createCriteria();
        if (StringUtils.isNotBlank(requestVo.getCorpId())) {
            criteria.andEqualTo("companyId", requestVo.getCorpId());
        }
        if (StringUtils.isNotBlank(requestVo.getTaskNo())) {
            criteria.andLike("taskNo", "%" + requestVo.getTaskNo() + "%");
        }
        example.setOrderByClause("create_Date desc");
        PageHelper.startPage(requestVo.getPageNum(), requestVo.getPageSize());
        List<MbOrgCostUpload> mbOrgCostUploads = mbOrgCostUploadMapper.selectByExample(example);
        PageInfo pageInfo = new PageInfo<>(mbOrgCostUploads);
        Page<MbOrgCostUpload> page = new Page(pageInfo.getPageNum(), pageInfo.getPageSize(), pageInfo.getPages(),
                pageInfo.getTotal(), mbOrgCostUploads);
        List<CostUploadInfoPageResponseVo.CostUploadInfoResponseVo> responseVos = new ArrayList<>();
        CostUploadInfoPageResponseVo pageResponseVo = new CostUploadInfoPageResponseVo();
        page.getList().stream().filter(item -> Objects.nonNull(item)).forEach(item -> {
            CostUploadInfoPageResponseVo.CostUploadInfoResponseVo responseVo =
                    new CostUploadInfoPageResponseVo.CostUploadInfoResponseVo();

            Example mbOrgCostUploadDetail = new Example(MbOrgCostUploadDetail.class);
            mbOrgCostUploadDetail.createCriteria().andEqualTo("taskNo",item.getTaskNo());
            MbOrgCostUploadDetail uploadDetail = mbOrgCostUploadDetailMapper.selectOneByExample(mbOrgCostUploadDetail);

            if(uploadDetail ==null){
                responseVo.setTaskNo(item.getTaskNo());
                responseVo.setFileName(item.getFileName());
                responseVo.setSuccessNumber(item.getSuccessNumber());
                responseVo.setFiledNumber(0);
                responseVo.setCountNumber(item.getSuccessNumber() + item.getFiledNumber());
                responseVo.setCompanyId(item.getCompanyId());
                responseVo.setCreateDate(item.getCreateDate());
                responseVo.setOperatorName(item.getOperatorName());
                responseVos.add(responseVo);
                return;
            }

            String errorDetail = uploadDetail.getFiledReason();
            String[] arrayAppDepart = Pattern.compile("[;；]").split(errorDetail);
            List<String> errorList = new ArrayList<>(Arrays.asList(arrayAppDepart));

            responseVo.setTaskNo(item.getTaskNo());
            responseVo.setFileName(item.getFileName());
            responseVo.setSuccessNumber(item.getSuccessNumber());
            responseVo.setFiledNumber(errorList.size());
            responseVo.setCountNumber(item.getSuccessNumber() + item.getFiledNumber());
            responseVo.setCompanyId(item.getCompanyId());
            responseVo.setCreateDate(item.getCreateDate());
            responseVo.setOperatorName(item.getOperatorName());
            responseVos.add(responseVo);
        });
        pageResponseVo.setUploadInfoResponseVos(responseVos);// 返回前端结果
        pageResponseVo.setCurrentPage(requestVo.getPageNum());
        pageResponseVo.setPageSize(requestVo.getPageSize());
        pageResponseVo.setTotalCount(Integer.parseInt(pageInfo.getTotal() + ""));
        pageResponseVo.setTotalPage(page.getTotalPage());
        return pageResponseVo;
    }

    public CostUploadInfoPageResponseVo selectUploadDetailInfoPage(CostUploadInfoPageRequestVo requestVo) {
        Example example = new Example(MbOrgCostUploadDetail.class);
        example.createCriteria().andLike("taskNo", "%" + requestVo.getTaskNo() + "%");
        PageHelper.startPage(requestVo.getPageNum(), requestVo.getPageSize());
        List<MbOrgCostUploadDetail> uploadDetailList = mbOrgCostUploadDetailMapper.selectByExample(example);
        PageInfo pageInfo = new PageInfo<>(uploadDetailList);
        Page<MbOrgCostUploadDetail> page = new Page(pageInfo.getPageNum(), pageInfo.getPageSize(), pageInfo.getPages(),
                pageInfo.getTotal(), uploadDetailList);
        List<CostUploadInfoPageResponseVo.CostUploadDetailInfoResponseVo> responseVos = new ArrayList<>();
        CostUploadInfoPageResponseVo pageResponseVo = new CostUploadInfoPageResponseVo();
        page.getList().stream().filter(item -> Objects.nonNull(item)).forEach(item -> {

            String errorDetail = item.getFiledReason();
            String[] arrayAppDepart = Pattern.compile("[;；]").split(errorDetail);
            List<String> errorList = new ArrayList<>(Arrays.asList(arrayAppDepart));

            for (int i = 0; i < errorList.size(); i++) {
                CostUploadInfoPageResponseVo.CostUploadDetailInfoResponseVo responseVo =
                        new CostUploadInfoPageResponseVo.CostUploadDetailInfoResponseVo();
                responseVo.setTaskNo(item.getTaskNo());
                responseVo.setLine(item.getLine());
                responseVo.setFiledReason(errorList.get(i));
                responseVos.add(responseVo);
            }
        });
        pageResponseVo.setUploadDetailInfoResponseVos(responseVos);// 返回前端结果
        pageResponseVo.setCurrentPage(requestVo.getPageNum());
        pageResponseVo.setPageSize(requestVo.getPageSize());
        pageResponseVo.setTotalCount(Integer.parseInt(pageInfo.getTotal() + ""));
        pageResponseVo.setTotalPage(page.getTotalPage());
        return pageResponseVo;
    }

    public void downloadUploadInfo(String taskNo, HttpServletResponse response) {
        Example uploadDetailExample = new Example(MbOrgCostUploadDetail.class);
        uploadDetailExample.createCriteria().andEqualTo("taskNo", taskNo);
        List<MbOrgCostUploadDetail> costUploadDetailList =
                mbOrgCostUploadDetailMapper.selectByExample(uploadDetailExample);
        List<CostUploadInfoDownloadResponseVo> responseVos = new ArrayList<>();
        costUploadDetailList.forEach(item -> {
            if(ObjectUtil.isNotEmpty(item.getValidStartDate())){
                item.setValidStartDate(
                        cn.hutool.core.date.DateUtil.parse(cn.hutool.core.date.DateUtil.format(item.getValidStartDate(),DatePattern.NORM_DATETIME_FORMAT), DatePattern.NORM_DATETIME_FORMAT));
            }
            if(ObjectUtil.isNotEmpty(item.getValidEndDate())){
                item.setValidEndDate(
                        cn.hutool.core.date.DateUtil.parse(cn.hutool.core.date.DateUtil.format(item.getValidEndDate(),DatePattern.NORM_DATETIME_FORMAT), DatePattern.NORM_DATETIME_FORMAT));
            }
            responseVos.add(new CostUploadInfoDownloadResponseVo(item.getOrgId(), item.getCostCenterName(),
                    item.getCostCenterCode(), item.getValidStartDate(), item.getValidEndDate(), item.getLine(), item.getFiledReason()));
        });

        Example uploadExample = new Example(MbOrgCostUpload.class);
        uploadExample.createCriteria().andEqualTo("taskNo", taskNo);
        List<MbOrgCostUpload> costUploadList = mbOrgCostUploadMapper.selectByExample(uploadExample);
        String fileName = "成本中心同步异常数据";
        ExcelPostEnum excelPostEnum = ExcelPostEnum.xlsx;
        if (CollectionUtils.isEmpty(costUploadList)) {
            fileName = costUploadList.get(0).getFileName().replace(".xls", "").replace(".xlsx", "");

            if (costUploadList.get(0).getFileName().endsWith("xls")) {
                excelPostEnum = ExcelPostEnum.xls;
            }
        }

        ExcelCreateVO<CostUploadInfoDownloadResponseVo> vo = ExcelCreateVO.<CostUploadInfoDownloadResponseVo>builder()
                .fileName(fileName)
                .dataList(responseVos)
                .postfix(excelPostEnum)
                .cls(CostUploadInfoDownloadResponseVo.class)
                .build();
        excelUtils.downloadExcelDocument(response, vo);
    }

    public void downloadCostCenter(String companyId, HttpServletResponse response) {
        GetProjectInfoRequest getProjectInfoRequest = new GetProjectInfoRequest();
        getProjectInfoRequest.setCompanyId(companyId);
        List<CostCenter> costCenterList = this.getCostCentersByCompanyId(getProjectInfoRequest);

        List<CostCenterInfoDownloadResponseVo> responseVos = new ArrayList<>();
        costCenterList.forEach(item -> {

            List<String> orgIds = item.getDepartments().stream().map(OrgInfo::getOrgId).collect(Collectors.toList());
            String businessCode = null;
            if (CollectionUtils.isNotEmpty(orgIds)) {
                JSONResult<List<OrgInfoVo>> orgInfoByOrgIds = organizationService.findOrgInfoByOrgIds(orgIds);
                if (orgInfoByOrgIds != null && CollectionUtils.isNotEmpty(orgInfoByOrgIds.getData())){
                    businessCode = orgInfoByOrgIds.getData().stream().map(OrgInfoVo::getBusinessCode)
                            .collect(Collectors.joining(","));
                }

            }
            if(ObjectUtil.isNotEmpty(item.getValidStartDate())){
                item.setValidStartDate(
                cn.hutool.core.date.DateUtil.parse(cn.hutool.core.date.DateUtil.format(item.getValidStartDate(),DatePattern.NORM_DATETIME_FORMAT), DatePattern.NORM_DATETIME_FORMAT));
            }
            if(ObjectUtil.isNotEmpty(item.getValidEndDate())){
                item.setValidEndDate(
                cn.hutool.core.date.DateUtil.parse(cn.hutool.core.date.DateUtil.format(item.getValidEndDate(),DatePattern.NORM_DATETIME_FORMAT), DatePattern.NORM_DATETIME_FORMAT));
            }
            responseVos.add(new CostCenterInfoDownloadResponseVo(businessCode, item.getCostCenterName(),
                    item.getCostCenterCode(), item.getValidStartDate(), item.getValidEndDate()));

        });
        String fileName = "成本中心信息";
        ExcelPostEnum excelPostEnum = ExcelPostEnum.xlsx;
        ExcelCreateVO<CostCenterInfoDownloadResponseVo> vo = ExcelCreateVO.<CostCenterInfoDownloadResponseVo>builder()
                .fileName(fileName)
                .dataList(responseVos)
                .postfix(excelPostEnum)
                .cls(CostCenterInfoDownloadResponseVo.class)
                .build();
        excelUtils.downloadExcelDocument(response, vo);
    }

    public MbOrgCostDefaultDepartment selectDefaultDepartmentByOrgId(String orgId) {
        Example example = new Example(MbOrgCostDefaultDepartment.class);
        example.createCriteria().andEqualTo("orgId", orgId).andEqualTo("isDelete", false);
        List<MbOrgCostDefaultDepartment> mbOrgCostDefaultDepartments =
                mbOrgCostDefaultDepartmentMapper.selectByExample(example);
        if (CollectionUtils.isNotEmpty(mbOrgCostDefaultDepartments)) {
            return mbOrgCostDefaultDepartments.get(0);
        }
        return null;
    }

    public Map<String, List<MbOrgCostDefaultDepartment>> selectDefaultDepartmentListByOrgIds(List<String> orgIds){
        if (CollectionUtils.isEmpty(orgIds)){
            return null;
        }
        Example example = new Example(MbOrgCostDefaultDepartment.class);
        example.createCriteria().andIn("orgId", orgIds).andEqualTo("isDelete", false);
        List<MbOrgCostDefaultDepartment> mbOrgCostDefaultDepartments =
                mbOrgCostDefaultDepartmentMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(mbOrgCostDefaultDepartments)){
            return null;
        }
        HashMap<String, List<MbOrgCostDefaultDepartment>> map = new HashMap<>();
        mbOrgCostDefaultDepartments.forEach(e ->{
            if (Objects.isNull(map.get(e.getOrgId()))){
                ArrayList<MbOrgCostDefaultDepartment> list = new ArrayList<>();
                list.add(e);
                map.put(e.getOrgId(), list);
            } else {
                map.get(e.getOrgId()).add(e);
            }
        });
        return map;
    }

    public List<MbOrgCostDefaultDepartment> selectDefaultDepartmentByOrgIds(List<String> orgIdList) {
        Example example = new Example(MbOrgCostDefaultDepartment.class);
        example.createCriteria().andIn("orgId", orgIdList).andEqualTo("isDelete", false);
        return mbOrgCostDefaultDepartmentMapper.selectByExample(example);
    }

    public List<MbOrgCostDefaultDepartment> selectDefaultDepartmentByCostId(Integer costInfoId) {
        Example example = new Example(MbOrgCostDefaultDepartment.class);
        example.createCriteria().andEqualTo("costInfoId", costInfoId).andEqualTo("isDelete", false);
        List<MbOrgCostDefaultDepartment> mbOrgCostDefaultDepartments =
                mbOrgCostDefaultDepartmentMapper.selectByExample(example);
        return mbOrgCostDefaultDepartments;
    }

    public boolean deleteDefaultDepartmentByCostId(Integer costInfoId) {
        Example example = new Example(MbOrgCostDefaultDepartment.class);
        example.createCriteria().andEqualTo("costInfoId", costInfoId).andEqualTo("isDelete", false);
        MbOrgCostDefaultDepartment defaultDepartment = new MbOrgCostDefaultDepartment();
        defaultDepartment.setIsDelete(true);
        defaultDepartment.setUpdateTime(new Date());
        return mbOrgCostDefaultDepartmentMapper.updateByExampleSelective(defaultDepartment, example) > 0;
    }

    /**
     * 根据code找到对应的name
     * @param request
     * @return
     */
    public CostCenterParamValidateResponse getCostCenter(CostCenterParamValidateRequest request) {

        CostCenterParamValidateResponse response = new CostCenterParamValidateResponse();

        List<String> orgIdList = request.getOrgId();
        List<MbOrgCostInfo> mbOrgCostInfoList = orgCostInfoMapper.selectByOrgIdList(orgIdList);

        Map<String, List<CostCenterParamValidateDTO>> orgIdCostCenterInfoMap = CollectionUtils.emptyIfNull(mbOrgCostInfoList)
                .stream().collect(Collectors.groupingBy(MbOrgCostInfo::getOrgId,
                    Collectors.mapping(
                        cst -> {
                            CostCenterParamValidateDTO dto = new CostCenterParamValidateDTO();
                            dto.setCostCenterName(cst.getCostCenterName());
                            // 存在成本中心的code为null的情况，也存在code为""的情况，将其都替换为""
                            dto.setCostCenterCode(Null.or(cst.getCostCenterCode(), ""));
                            return dto;
                        }, Collectors.toList())));

        Map<String, Map<String, Set<String>>> orgIdCostInfoMap = CollectionUtils.emptyIfNull(mbOrgCostInfoList).stream()
                .collect(Collectors.groupingBy(MbOrgCostInfo::getOrgId,
                    Collectors.groupingBy((MbOrgCostInfo m) -> Null.or(m.getCostCenterCode(), ""),
                        Collectors.mapping(MbOrgCostInfo::getCostCenterName, Collectors.toSet()))));

        response.setCostCenterParamValidateDTOS(
            orgIdCostCenterInfoMap.values().stream().flatMap(List::stream).collect(Collectors.toList()));
        response.setOrgIdCostInfoMap(orgIdCostInfoMap);
        response.setOrgIdCostCenterInfoMap(orgIdCostCenterInfoMap);
        return response;
    }

    /**
     * 手动更新处，下拉框模糊查询
     *
     * @param request
     * @return
     */
    public GetCostCenterListResponse queryCostCenterNameCode(GetCostCenterListRequest request) {
        log.info("成本中心名称/编码request参数：" + request);

        GetCostCenterListResponse response = new GetCostCenterListResponse();
        List<CostCenter> costCenterList = new ArrayList<>();

        // costCenterName 存入数据库是加密的，因此，进行模糊搜索时也是直接搜索的加密，不能直接查询数据库
        // SELECT * FROM MbOrgCostInfo WHERE companyId = request.getOrgId() and isDelete = false;
        Example example = new Example(MbOrgCostInfo.class);
        Example.Criteria exampleJoin = example.createCriteria()
                .andEqualTo("isDelete", false)
                .andEqualTo("valid",true);

        List<String> orgIds = new ArrayList<>();
        // 查询登录用户的数据权限
        if(StrUtil.isNotBlank(request.getQueryType()) && request.getQueryType().equalsIgnoreCase("userPermission")){
            Object dataPermissionOrgIdList = RequestContext.getCurrentContext().getContextParams(DATA_PERMISSION_ORG_ID_LIST);
            // 如果为空则说明是超级管理员，直接查询所有。否则查询对应的数据权限
            if (dataPermissionOrgIdList != null) {
                // assert dataPermissionOrgIdList instanceof List
                orgIds = (List<String>) dataPermissionOrgIdList;
            }

            log.info("查询登录用户的数据权限:{}",JsonUtils.toJsonString(orgIds));
            if(CollectionUtils.isNotEmpty(orgIds)){
                exampleJoin.andIn("companyId", orgIds);
            }
        }

        // FIXME 此处与产品确认，如果dataPermissionOrgIdList为空，那么就认定是超级管理员，那么就查询所有
        /*if(CollectionUtils.isEmpty(orgIds)){
            exampleJoin.andEqualTo("companyId", request.getOrgId());
        }*/


        Example.Criteria criteriaStartDate = example.createCriteria();
        criteriaStartDate.andIsNull("validStartDate").orLessThanOrEqualTo("validStartDate",LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));

        Example.Criteria criteriaEndDate = example.createCriteria();
        criteriaEndDate.andIsNull("validEndDate").orGreaterThanOrEqualTo("validEndDate",LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));

        example.and(criteriaStartDate);
        example.and(criteriaEndDate);

        log.info("key:" + request.getKey());
        // KEY 是当前请求传递的参数，也就是输入框中的搜索参数，可以为空
        if (!StringUtils.isBlank(request.getKey())) {
            List<MbOrgCostInfo> orgCostInfoList = orgCostInfoMapper.listAll();
            /*
              代码逻辑是：
              首先，查询出所有的记录
              之后，判断当前记录中的两个字段，是否包含通过 request 获得的 key ----- 此时，给前端返回的是记录中所有的数值，不是单个字段，List
             */
            List<Integer> ids = orgCostInfoList.stream()
                    .filter(e -> StringUtils.contains(e.getCostCenterName(), request.getKey())  // StringUtils.contains 前者是否包含后者，空字符串也返回true
                            || StringUtils.contains(e.getCostCenterCode(), request.getKey()))
                    .map(MbOrgCostInfo::getId)
                    .collect(Collectors.toList());
            if (CollectionUtils.isEmpty(ids)) {
                return response;
            }
            log.info("当前公司id下，全部成本中心为：" + orgCostInfoList);
            // SELECT * FROM MbOrgCostInfo WHERE companyId = request.getOrgId() and isDelete = false and in(......)
            exampleJoin.andIn("id", ids);
        }
        example.setOrderByClause("datachange_lasttime DESC");
        IPage<MbOrgCostInfo> pageInfo = PageContext.startPage(request.getCurrentPage(), request.getPageSize());
        orgCostInfoMapper.selectByExample(example);

        // 类型转换 MbOrgCostInfo ---> costcenter
        for (MbOrgCostInfo info : pageInfo.getRecords()) {
            CostCenter item = transfer(info);
            costCenterList.add(item);
        }

        log.info("模糊查询的成本中心为：" + costCenterList);
        response.setCostCenterList(costCenterList);// 返回前端结果
        response.setCurrentPage(request.getCurrentPage());
        response.setPageSize(request.getPageSize());
        response.setTotalCount((int)pageInfo.getTotal());
        response.setTotalPage((int)pageInfo.getPages());

        log.info("成本中心名称/编码response参数：" + response);
        return response;
    }

    public GetCostCenterListResponse queryCostCenterByOrgScope(GetCostCenterListRequest request) {
        GetCostCenterListResponse response = new GetCostCenterListResponse();
        BaseUserInfo baseUserInfo = UserInfoContext.getContextParams(BaseUserInfo.class);

        List<String> orgIds = Lists.newArrayList();

        if (Objects.nonNull(baseUserInfo)  && !Boolean.TRUE.equals(baseUserInfo.getBgUser())) {
            if (Boolean.TRUE.equals(baseUserInfo.getDataPermissionControl())) {
                orgIds = Optional.ofNullable(DataPermissionsContext.getRoleAllDataPermissions())
                        .map(ResourceInfo::getDeptInfos)
                        .orElse(new ArrayList<>())
                        .stream()
                        .map(ResourceInfo.DeptInfo::getOrgId)
                        .collect(Collectors.toList());
            }
        }
        IPage<MbOrgCostInfo> pageInfo = PageContext.startPage(request.getCurrentPage(), request.getPageSize());
        orgCostInfoMapper.selectCostCenterByOrgScope(orgIds, request.getKey());

        List<CostCenter> costCenterList =
        pageInfo.getRecords().stream().map(item -> {
            CostCenter costCenter = new CostCenter();
            costCenter.setId(item.getId());
            costCenter.setCostCenterCode(item.getCostCenterCode());
            costCenter.setCostCenterName(item.getCostCenterName());
            return costCenter;
        }).collect(Collectors.toList());
        response.setCostCenterList(costCenterList);// 返回前端结果
        response.setCurrentPage(request.getCurrentPage());
        response.setPageSize(request.getPageSize());
        response.setTotalCount((int)pageInfo.getTotal());
        response.setTotalPage((int)pageInfo.getPages());
        return response;
    }

    public void updateNames(String id) {
        List<MbOrgCostInfo> mbOrgCostInfos;
        if ("*".equals(id)) {
            mbOrgCostInfos = orgCostInfoMapper.selectAll();
        } else {
            mbOrgCostInfos = Collections.singletonList(orgCostInfoMapper.selectByPrimaryKey(id));
        }

        for (MbOrgCostInfo costInfo : mbOrgCostInfos) {
            orgCostInfoMapper.updateByPrimaryKey(costInfo);
        }
    }

    public void saveCostCenterInfoByOrg(String orgId, List<AddOrgRequest.CostCenterInfo> costCenterInfoList) {
        if (CollectionUtils.isEmpty(costCenterInfoList)) {
            return;
        }
        // 用户信息
        BaseUserInfo baseUserInfo = UserInfoContext.getContextParams(BaseUserInfo.class);
        // 组织信息
        MbOrgInfo mbOrgInfo = organizationInfoService.findByOrgId(orgId);
        // 直属公司信息
        MbOrgInfo companyOrgInfo = organizationInfoService.findRecentCompanyIdByOrgId(orgId);
        // 成本中心分组信息
        Map<String, MbOrgCostInfo> costCenterCodeMap = costCenterCodeMapByCompany(companyOrgInfo.getOrgId());
        // 遍历成本中心进行保存关联
        for (AddOrgRequest.CostCenterInfo costCenterInfo : costCenterInfoList) {
            if (StringUtils.isBlank(costCenterInfo.getCostCenterCode())
                || StringUtils.isBlank(costCenterInfo.getCostCenterName())) {
                continue;
            }
            MbOrgCostInfo mbOrgCostInfo = costCenterCodeMap.get(costCenterInfo.getCostCenterCode());
            // 已经在公司纬度中存在
            if (null != mbOrgCostInfo) {
                List<MbOrgCostDepartment> costDepartmentList =
                    this.getCostDepartmentList(Sets.newHashSet(mbOrgCostInfo.getId()));

                if (costDepartmentList.stream().anyMatch(item -> item.getOrgId().equalsIgnoreCase(orgId))) {
                    continue;
                }
                // 绑定关联关系
                MbOrgCostDepartment mbOrgCostDepartment =
                    packageOrgCostDepartment(mbOrgCostInfo.getId(), mbOrgInfo.getOrgId(), mbOrgInfo.getName());
                orgCostDepartmentMapper.insert(mbOrgCostDepartment);
                continue;
            }
            // 新增成本中心
            MbOrgCostInfo addOrgCostInfo = packageOrgCostInfo(companyOrgInfo.getOrgId(), companyOrgInfo.getName(),
                costCenterInfo.getCostCenterCode(), costCenterInfo.getCostCenterName(), baseUserInfo.getUid(),
                baseUserInfo.getUserName());
            orgCostInfoMapper.insert(addOrgCostInfo);
            if (null != addOrgCostInfo.getId()) {
                // 绑定关联关系
                MbOrgCostDepartment mbOrgCostDepartment =
                    packageOrgCostDepartment(addOrgCostInfo.getId(), mbOrgInfo.getOrgId(), mbOrgInfo.getName());
                orgCostDepartmentMapper.insert(mbOrgCostDepartment);
            }
        }
    }

    public Map<String, MbOrgCostInfo> costCenterCodeMapByCompany(String companyId) {
        // 查询直属公司下所有成本中心
        CostCenter queryCostCenter = new CostCenter();
        queryCostCenter.setCompanyId(companyId);
        List<MbOrgCostInfo> mbOrgCostInfoList = this.select(queryCostCenter);
        // 分组，key：成本中心编码
        return Optional.ofNullable(mbOrgCostInfoList).orElse(new ArrayList<>())
            .stream().filter(cost -> StringUtils.isNotBlank(cost.getCostCenterCode()))
            .collect(Collectors.toMap(MbOrgCostInfo::getCostCenterCode, Function.identity(), (k1, k2) -> k1));
    }

    private MbOrgCostInfo packageOrgCostInfo(String companyId, String companyName, String costCenterCode,
        String costCenterName, String uid, String uname) {
        MbOrgCostInfo costInfo = new MbOrgCostInfo();
        costInfo.setCompany(companyName);
        costInfo.setCompanyId(companyId);
        costInfo.setCostCenterCode(costCenterCode);
        costInfo.setCostCenterName(costCenterName);
        costInfo.setValid(Boolean.TRUE);
        costInfo.setIsDelete(Boolean.FALSE);
        costInfo.setOperatorUid(uid);
        costInfo.setOperatorName(uname);
        costInfo.setCreateDate(new Date());
        costInfo.setCreateTime(new Date());
        costInfo.setUpdateTime(new Date());
        return costInfo;
    }

    private MbOrgCostDepartment packageOrgCostDepartment(Integer costId, String orgId, String orgName) {
        MbOrgCostDepartment costDepartment = new MbOrgCostDepartment();
        costDepartment.setCostInfoId(costId);
        costDepartment.setOrgId(orgId);
        costDepartment.setOrgName(orgName);
        costDepartment.setCreateTime(new Date());
        costDepartment.setUpdateTime(new Date());
        return costDepartment;
    }

    public CostCenterInfoRspVo queryCostCenterInfoPage(CostCenterInfoVo request) {
        if (StringUtils.isBlank(request.getOrgId())) {
            return null;
        }
        MbOrgInfo companyOrgInfo = organizationInfoService.findRecentCompanyIdByOrgId(request.getOrgId());
        if (null == companyOrgInfo) {
            return null;
        }
        CostCenter costCenter = new CostCenter();
        costCenter.setCompanyId(companyOrgInfo.getOrgId());
        IPage<MbOrgCostInfo> costInfoIPage = PageContext.startPage(request.getCurrentPage(), request.getPageSize());
        this.select(costCenter);
        CostCenterInfoRspVo response = new CostCenterInfoRspVo();
        response.setCurrentPage((int)costInfoIPage.getCurrent());
        response.setPageSize((int)costInfoIPage.getSize());
        response.setTotalCount((int)costInfoIPage.getTotal());
        response.setTotalPage((int)costInfoIPage.getPages());
        IPage<CostCenterInfoRspVo.CostCenter> convertCenter = costInfoIPage.convert(data -> {
            CostCenterInfoRspVo.CostCenter costCenterVo = new CostCenterInfoRspVo.CostCenter();
            costCenterVo.setCostCenterCode(data.getCostCenterCode());
            costCenterVo.setCostCenterName(data.getCostCenterName());
            return costCenterVo;
        });
        response.setCostCenterList(convertCenter.getRecords());
        return response;
    }

    /**
     * 查询机构id查询部门直挂的公司或者公司成本中心列表
     * @param request
     * @return
     */
    public List<CostCenterInfoRspVo.CostCenter> queryCostCenterListByOrgId(CostCenterInfoVo request) {
        if (StringUtils.isBlank(request.getOrgId())) {
            return Collections.emptyList();
        }
        MbOrgInfo companyOrgInfo = organizationInfoService.findRecentCompanyIdByOrgId(request.getOrgId());
        if (null == companyOrgInfo || null == companyOrgInfo.getOrgId() ) {
            return Collections.emptyList();
        }

        List<MbOrgCostInfo> mbOrgCostInfos = orgCostInfoMapper.selectByCompanyId(companyOrgInfo.getOrgId());
        if (CollectionUtils.isNotEmpty(mbOrgCostInfos)) {
            List<CostCenterInfoRspVo.CostCenter> costCenterList = new ArrayList<>();
                mbOrgCostInfos.forEach(e -> {
                    CostCenterInfoRspVo.CostCenter costCenterVo = new CostCenterInfoRspVo.CostCenter();
                    costCenterVo.setCostCenterCode(e.getCostCenterCode());
                    costCenterVo.setCostCenterName(e.getCostCenterName());
                    costCenterList.add(costCenterVo);
                });
            return costCenterList;
        }
        return Collections.emptyList();
    }

    /**
     * 保存默认成本中心
     * @param orgId
     * @param costCenterDefaultInfo
     */
    public void saveOrgCostDefaultDepartmentByOrg(String orgId, AddOrgRequest.CostCenterInfo costCenterDefaultInfo) {

        if(null == costCenterDefaultInfo || null == costCenterDefaultInfo.getCostCenterCode()) {
            return;
        }
        // 直属公司信息
        MbOrgInfo companyOrgInfo = organizationInfoService.findRecentCompanyIdByOrgId(orgId);
        if(null == companyOrgInfo || null == companyOrgInfo.getOrgId()) {
            return;
        }
        // 获取成本中心id
        Example example = new Example(MbOrgCostInfo.class);
        example.createCriteria().andEqualTo("costCenterCode", costCenterDefaultInfo.getCostCenterCode())
                .andEqualTo("companyId", companyOrgInfo.getOrgId()).andEqualTo("isDelete", false);
        example.setOrderByClause("datachange_lasttime DESC");
        List<MbOrgCostInfo> costInfos = orgCostInfoMapper.selectByExample(example);
        if(CollectionUtils.isEmpty(costInfos) || null == costInfos.get(0) || null == costInfos.get(0).getId() ) {
            log.info("{}的默认成本中心{}不存在" , orgId, costCenterDefaultInfo.getCostCenterCode());
            return;
        }

        // 删除该组织和默认成本中心的关系
        Example exampleDefault = new Example(MbOrgCostDefaultDepartment.class);
        exampleDefault.createCriteria().andEqualTo("orgId", orgId);
        mbOrgCostDefaultDepartmentMapper.deleteByExample(exampleDefault);

        // 该组织未设置默认成本中心 直接绑定该成本中心未默认成本中心
        MbOrgCostDefaultDepartment defaultDepartment = new MbOrgCostDefaultDepartment();
        defaultDepartment.setCostInfoId(costInfos.get(0).getId());
        defaultDepartment.setOrgId(orgId);
        defaultDepartment.setCreateTime(new Date());
        defaultDepartment.setUpdateTime(new Date());
        defaultDepartment.setIsDelete(false);
        mbOrgCostDefaultDepartmentMapper.insert(defaultDepartment);
    }

    /**
     * 删除成本中心机构关系
     * @param orgId
     * @return
     */
    public boolean deleteCostDepartmentByOrgId(String orgId, int type) {
        if (StringUtils.isBlank(orgId)) {
            return false;
        }
        if(type == 1) {
            // 删除该组织和成本中心的关系
            Example example = new Example(MbOrgCostDepartment.class);
            example.createCriteria().andEqualTo("orgId", orgId);
            orgCostDepartmentMapper.deleteByExample(example);
        }
       if(type == 2) {
           // 删除该组织和默认成本中心的关系
           Example exampleDefault = new Example(MbOrgCostDefaultDepartment.class);
           exampleDefault.createCriteria().andEqualTo("orgId", orgId);
           mbOrgCostDefaultDepartmentMapper.deleteByExample(exampleDefault);
       }
       return true;
    }

}
